package com.ruoyi.file.service.impl;

import java.io.*;
import java.util.Date;
import java.util.List;
import com.ruoyi.common.core.domain.ResultResponse;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.security.Md5Utils;
import com.ruoyi.file.domain.FileConf;
import com.ruoyi.file.mapper.FileConfMapper;
import com.ruoyi.file.service.IFtpFileService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.ruoyi.file.mapper.FileInfoMapper;
import com.ruoyi.file.domain.FileInfo;
import com.ruoyi.file.service.IFileInfoService;
import com.ruoyi.common.core.text.Convert;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

/**
 * 文件信息Service业务层处理
 * 
 * @author shushuang
 * @date 2019-11-27
 */
@Service
@Slf4j
public class FileInfoServiceImpl implements IFileInfoService 
{


    @Autowired
    private FileInfoMapper fileInfoMapper;

    @Autowired
    private FileConfMapper fileConfMapper;

    @Autowired
    private IFtpFileService iFtpFileService;

    private static int counter = 0;

    @Value("${ftp.rootdirectory}")
    private String rootdirectory;

    /**
     * 查询文件信息
     * 
     * @param id 文件信息ID
     * @return 文件信息
     */
    @Override
    public FileInfo selectFileInfoById(Long id)
    {
        return fileInfoMapper.selectFileInfoById(id);
    }

    /**
     * 查询文件信息列表
     * 
     * @param fileInfo 文件信息
     * @return 文件信息
     */
    @Override
    public List<FileInfo> selectFileInfoList(FileInfo fileInfo)
    {
        return fileInfoMapper.selectFileInfoList(fileInfo);
    }

    /**
     * 新增文件信息
     * 
     * @param fileInfo 文件信息
     * @return 结果
     */
    @Override
    public int insertFileInfo(FileInfo fileInfo)
    {
        return fileInfoMapper.insertFileInfo(fileInfo);
    }

    /**
     * 修改文件信息
     * 
     * @param fileInfo 文件信息
     * @return 结果
     */
    @Override
    public int updateFileInfo(FileInfo fileInfo)
    {
        return fileInfoMapper.updateFileInfo(fileInfo);
    }

    /**
     * 删除文件信息对象
     * 
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteFileInfoByIds(String ids)
    {
        return fileInfoMapper.deleteFileInfoByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除文件信息信息
     * 
     * @param id 文件信息ID
     * @return 结果
     */
    @Override
    public int deleteFileInfoById(Long id)
    {
        return fileInfoMapper.deleteFileInfoById(id);
    }

    @Override
    public ResultResponse uploadFile(MultipartFile file, String bizeType) throws Exception {
        ResultResponse resultResponse = new ResultResponse();
        //根据业务类型判断是否符合上传条件标准----------------
        FileConf fileConf = new FileConf();
        fileConf.setBizeType(bizeType);
        List<FileConf> fileConfs = fileConfMapper.selectFileConfList(fileConf);
        if(fileConfs == null || fileConfs.size() != 1){
            log.info("业务类型不存在或者存在多条");
            resultResponse.setShuCode("error");
            resultResponse.setMsg("业务类型不存在或者存在多条");
            return resultResponse;
        }
        String path = fileConfs.get(0).getPath();
        Long fileSizeLimit = fileConfs.get(0).getFileSizeLimit();
        String fileTypeLimit = fileConfs.get(0).getFileTypeLimit();

        //这里得到的size是文件大小，contentType是文件类型(mine-type标准)
        long size = file.getSize();
        String contentType = file.getContentType();

        if (fileSizeLimit != null && size > fileSizeLimit * 1024) {
            //文件大了
            log.info("{}业务限制文件大小为: {}kb,实际上传文件大小为{}kb", bizeType, fileSizeLimit, size / 1024);
            resultResponse.setShuCode("error");
            resultResponse.setMsg(bizeType+"业务限制文件大小为: " + fileSizeLimit + "kb,实际上传文件大小为: "+size / 1024+"kb");
            return resultResponse;
        }
        String[] fileTypeLimits = fileTypeLimit.split(",");
        Boolean boo = false;
        for (String fileType: fileTypeLimits) {
            if(contentType.equals(fileType)){
                //存在，上传的文件类型在允许范围内
                boo = true;
                contentType = fileType;
                break;
            }
        }
        if(!boo){
            log.info("文件类型不在上传的范围内");
            resultResponse.setShuCode("error");
            resultResponse.setMsg("文件类型不在上传的范围内");
            return resultResponse;
        }

        //执行上传文件-----------------------------------------------------------------
        String newFileName = encodingFilename(file.getName()) + "." + FileUploadUtils.getExtension(file);
        String elativefilePath = path +"/" + DateUtils.datePath();

        InputStream inputStream = file.getInputStream();
        ResultResponse resultResponseftp = iFtpFileService.uploadFtpFile(elativefilePath, newFileName, inputStream);

        if(!resultResponseftp.isSuccess()){
            log.info("文件上传失败,文件名: {}", file.getName());
            resultResponse.setShuCode("error");
            resultResponse.setMsg("文件上传失败");
            return resultResponse;
        }

        //保存上传的文件信息到数据库
        FileInfo fileInfo = new FileInfo();
        fileInfo.setBizeType(bizeType);
        fileInfo.setOriginalName(file.getOriginalFilename());
        fileInfo.setNewName(newFileName);
        fileInfo.setFileType(contentType);
        fileInfo.setFileSize(size / 1024);
        fileInfo.setFilePath(rootdirectory+"/"+ elativefilePath + "/" + newFileName);
        String relativePath = elativefilePath + "/" + newFileName;
        fileInfo.setRelativePath(relativePath);
        Date date = new Date();
        fileInfo.setCreatTime(date);
        fileInfo.setUpdateTime(date);
        fileInfo.setDelFlag(0);
        if(fileInfoMapper.insertFileInfo(fileInfo) !=1){
            log.info("文件上传信息保存失败,文件名: {}", file.getName());
            resultResponse.setShuCode("error");
            resultResponse.setMsg("文件上传信息保存失败");
            return resultResponse;
        }
        resultResponse.put("relativePath",relativePath);
        resultResponse.put("fileInfoId", fileInfo.getId() );
        //得到访问文件地址并返回-----------------------------------------
        return resultResponse;
    }


    public static File multipartFileToFile(MultipartFile file) throws Exception {

        File toFile = null;
        if (file.equals("") || file.getSize() <= 0) {
            file = null;
        } else {
            InputStream ins = null;
            ins = file.getInputStream();
            toFile = new File(file.getOriginalFilename());
            inputStreamToFile(ins, toFile);
            ins.close();
        }
        return toFile;
    }

    //获取流文件
    private static void inputStreamToFile(InputStream ins, File file) {
        try {
            OutputStream os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            ins.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    /**
     * 编码文件名
     */
    private static final String encodingFilename(String fileName)
    {
        fileName = fileName.replace("_", " ");
        fileName = Md5Utils.hash(fileName + System.nanoTime() + counter++);
        return fileName;
    }



}
